package cn.iocoder.yudao.module.wms.service.rdrecord07;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
import cn.iocoder.yudao.module.bpm.service.task.ActHiProcinstServiceImpl;
import cn.iocoder.yudao.module.wms.controller.admin.rdrecord07.vo.Rdrecord07PageReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.rdrecord07.vo.Rdrecord07SaveReqVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.rdrecord07.Rdrecord07DO;
import cn.iocoder.yudao.module.wms.dal.dataobject.rdrecord07.Rdrecords07DO;
import cn.iocoder.yudao.module.wms.dal.dataobject.stock.StockDO;
import cn.iocoder.yudao.module.wms.dal.mysql.rdrecord07.Rdrecord07Mapper;
import cn.iocoder.yudao.module.wms.dal.mysql.rdrecord07.Rdrecords07Mapper;
import cn.iocoder.yudao.module.wms.dal.redis.RedisKeyConstants;
import cn.iocoder.yudao.module.wms.dal.redis.serialNumber.WmsSerialNumberRedisDAO;
import cn.iocoder.yudao.module.wms.service.inventory.stock.InventoryStockService;
import cn.iocoder.yudao.module.wms.service.stock.StockService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.RDRECORD07_NOT_EXISTS;
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.RDRECORDS07_SERIALNUMBER_EXISTS;

/**
 * 调拨出库主 Service 实现类
 *
 * @author 曾劲松
 */
@Service
@Validated
public class Rdrecord07ServiceImpl implements Rdrecord07Service {

    /**
     * OA 对应的流程定义 KEY
     */
    public static final String PROCESS_KEY = "rdrecord07-flow";
    @Resource
    private BpmProcessInstanceApi processInstanceApi;
    @Resource
    private Rdrecord07Mapper rdrecord07Mapper;
    @Resource
    private Rdrecords07Mapper rdrecords07Mapper;
    @Resource
    private ActHiProcinstServiceImpl actHiProcinstService;
    @Resource
    private WmsSerialNumberRedisDAO serialNumberRedisDAO;
    @Resource
    private StockService stockService;
    @Resource
    private InventoryStockService inventoryStockService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createRdrecord07(Rdrecord07SaveReqVO createReqVO) {
        String serialNumber = serialNumberRedisDAO.generate(WmsSerialNumberRedisDAO.RD07_SERIAL_PREFIX, RedisKeyConstants.SERIAL07);
        if (rdrecord07Mapper.selectBySerialNumber(serialNumber) != null) {
            throw exception(RDRECORDS07_SERIALNUMBER_EXISTS);
        }
        // 插入
        Rdrecord07DO rdrecord07 = BeanUtils.toBean(createReqVO, Rdrecord07DO.class,in -> in.setSerialNumber(serialNumber));
        rdrecord07Mapper.insert(rdrecord07);

        // 插入子表
        createRdrecords07List(rdrecord07.getId(), createReqVO.getRdrecords07s());
        // 返回
        return rdrecord07.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void process(Long id) {
        // 发起 BPM 流程
        Map<String, Object> processInstanceVariables = new HashMap<>();
        String processInstanceId = processInstanceApi.createProcessInstance(getLoginUserId(),
                new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
                        .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(id)));
        // 将工作流的编号，更新到 业务表单中
        rdrecord07Mapper.updateById(new Rdrecord07DO().setId(id).setProcessInstanceId(processInstanceId).setStatus(BpmTaskStatusEnum.RUNNING.getStatus()));

        //将链接加入到ACT_HI_PROCINST表中
        actHiProcinstService.updateURLById("/inventory/rdrecord07FormInfo?id=" + id,processInstanceId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRdrecord07(Rdrecord07SaveReqVO updateReqVO) {
        // 校验存在
        validateRdrecord07Exists(updateReqVO.getId());
        // 更新
        Rdrecord07DO updateObj = BeanUtils.toBean(updateReqVO, Rdrecord07DO.class);
        rdrecord07Mapper.updateById(updateObj);

        // 更新子表
        updateRdrecords07List(updateReqVO.getId(), updateReqVO.getRdrecords07s());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRdrecord07Status(Long id, Integer status) {
        // 校验存在
        validateRdrecord07Exists(id);
        if (status.equals(BpmTaskStatusEnum.APPROVE.getStatus())) {
            //结束则更新审核人
            rdrecord07Mapper.updateById(new Rdrecord07DO().setId(id).setStatus(status).setAuditor(String.valueOf(getLoginUserId())).setAuditTime(LocalDateTime.now()));
        } else {
            rdrecord07Mapper.updateById(new Rdrecord07DO().setId(id).setStatus(status));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRdrecord07(Long id) {
        // 校验存在
        validateRdrecord07Exists(id);
        // 删除
        rdrecord07Mapper.deleteById(id);

        // 删除子表
        deleteRdrecords07ByOrderId(id);
    }

    private void validateRdrecord07Exists(Long id) {
        if (rdrecord07Mapper.selectById(id) == null) {
            throw exception(RDRECORD07_NOT_EXISTS);
        }
    }

    @Override
    public Rdrecord07DO getRdrecord07(Long id) {
        return rdrecord07Mapper.selectById(id);
    }

    @Override
    public Rdrecord07DO getRdrecord07ByProcessInstanceId(String processInstanceId) {
        return rdrecord07Mapper.selectByProcessInstanceId(processInstanceId);
    }

    @Override
    public PageResult<Rdrecord07DO> getRdrecord07Page(Rdrecord07PageReqVO pageReqVO) {
        return rdrecord07Mapper.selectPage(pageReqVO,getCondition(pageReqVO.getPersonId()),
                getCondition(pageReqVO.getDeptId()),getCondition(pageReqVO.getOutWarehouseId()),
                getCondition(pageReqVO.getInWarehouseId()),getCondition(pageReqVO.getCreator()),
                getCondition(pageReqVO.getAuditor()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void businessProcessing(Long id, int type) {
        // 校验存在
        validateRdrecord07Exists(id);
        Rdrecord07DO rdrecord07 = rdrecord07Mapper.selectById(id);
        //获取子表信息
        List<Rdrecords07DO> rdrecords07DOList = rdrecords07Mapper.selectListByOrderId(id);
        for (Rdrecords07DO rdrecords07 : rdrecords07DOList) {
            //执行出库方法
            StockDO stockDO = new StockDO().setQty(rdrecords07.getQuantity() * type).setInventoryId(convertInteger(rdrecords07.getInventoryId()))
                    .setWarehouseId(convertInteger(rdrecord07.getOutWarehouseId())).setLocationId(convertInteger(rdrecords07.getLocationId()))
                    .setBatchCode(rdrecords07.getBatch());
            stockService.Outbound(stockDO);
        }
        for (Rdrecords07DO rdrecords07 : rdrecords07DOList) {
            //执行入库方法
            StockDO stockDO = new StockDO().setQty(rdrecords07.getQuantity() * type).setInventoryId(convertInteger(rdrecords07.getInventoryId()))
                    .setWarehouseId(convertInteger(rdrecord07.getInWarehouseId())).setLocationId(convertInteger(rdrecords07.getLocationId()))
                    .setBatchCode(rdrecords07.getBatch());
            stockService.store(stockDO);
        }
    }

    // ==================== 子表（调拨出库子） ====================

    @Override
    public List<Rdrecords07DO> getRdrecords07ListByOrderId(Long orderId) {
        return rdrecords07Mapper.selectListByOrderId(orderId);
    }

    private void createRdrecords07List(Long orderId, List<Rdrecords07DO> list) {
        list.forEach(o -> o.setOrderId(orderId));
        rdrecords07Mapper.insertBatch(list);
        businessProcessing(orderId,1);
    }

    private void updateRdrecords07List(Long orderId, List<Rdrecords07DO> list) {
        deleteRdrecords07ByOrderId(orderId);
        createRdrecords07List(orderId, list);
    }

    private void deleteRdrecords07ByOrderId(Long orderId) {
        businessProcessing(orderId,-1);
        rdrecords07Mapper.deleteByOrderId(orderId);
    }

    /**
     * 去空转换
     * @param ids id
     * @return id集合
     */
    private Set<String> getCondition(String[] ids) {
        if (ids == null) {
            return Collections.emptySet();
        }
        return new HashSet<>(Arrays.asList(ids));
    }

    /**
     * long转Integer
     * @param param 参数
     * @return Integer
     */
    private Integer convertInteger(Long param) {
        return Integer.valueOf(String.valueOf(param));
    }
}